var TagSupport = {
	// options = {id,formSubmit,formQuery,url,type,dataType,async,timeout,cache,
	//	onSuccess,onError,autoSend,silent,onBeforeSend,onComplete,contentType, htmlEncodeNames, successMonitors,
	//	respDataKey}
	'ajax':function(options) {
		ObjectUtil.cleanup(options, ['onBeforeSend','onComplete','onSuccess','onError','onServiceError']);
		if (StringUtil.isNotEmpty(options.data)) {
			var s = "var x = " + options.data;
			eval(s);
			options.data = x;
			options.odata = x;
		}
		var opt = {
			'formSubmit':(StringUtil.isEmpty(options.formQuery)  ? false : true),
			'silent':false,
			'autoSend':false,
			'contentType':'application/json',
			'type':'get',
			'dataType':'json',
			'monitors': null,
			'respDataKey': null
		};
		opt = $.extend(opt, FunctionEmbedUtil); // 具备执行函数队列的能力，embedFunction,executeEmbedFunctions
		opt = $.extend(opt, options);
		
		opt.successMonitorsArr = opt.successMonitors && (function() {
			var tempArr = new Array();
			var strArr = opt.successMonitors.split(",");
			$.each(strArr, function(index, item) {
				tempArr.push(window[item]);
			});
			return tempArr;
		})();
		
		var ajaxSetting = {
			'send':function() {
				if (this.formSubmit && StringUtil.isNotEmpty(this.formQuery)) {
					var frmData = $(this.formQuery).serializeObject();
					this.odata = {};
					$.extend(this.odata, this.data); // 将扩展form 的数据前的data备份至this.odata，以便恢复
					frmData = $.extend(this.data, frmData);
					
					// html encode 指定的属性
					var htmlEncodeNames = [];
					if (opt.htmlEncodeNames) {
						htmlEncodeNames = opt.htmlEncodeNames.split(",");
						if (htmlEncodeNames.length > 0) {
							$.each(htmlEncodeNames, function(index, name) {
								frmData[name] = Util.htmlEncode(frmData[name]);
							});
						}
					}
					
					$(this.formQuery).ajaxFormUnbind();
					var mFormSetting = {
						'data':frmData
					};
					var formSetting = $.extend(this, mFormSetting);
					$(this.formQuery).ajaxForm(formSetting);
				}
				$.mAjax(this);
				this.urlRestore();
				this.data = this.odata; // 不保留form带来的数据
			},
			'urlRestore':function() {
				if (this.oUrl) {
					this.url = this.oUrl;
					this.oUrl = null;
				}
			},
			'success':function(data,status,xhr) {
				if(!data){
					Logger.debug("ajax => " + this.id + "没有返回任何数据！");
					return ;
				}
				if(data.success==false || data.success == 'false'){ // data 中可能没有 isSuccess 属性
					var message = data.message || "系统错误";
					MsgBox.error(message, null, function() {
						opt.executeEmbedFunctions(function(item){
							item && item(data, status, xhr);
						}, 'onServiceError', this);
						opt.onServiceError && opt.onServiceError(data,status,xhr);
					});
					Logger.error("ajax send error , message: " + message);
					return ;
				}
				if (StringUtil.isNotBlank(opt.respDataKey)) {
					window[opt.respDataKey] = data.info;
				}
				// 是否根据后台返回来进行提示，当存在onSucccess，prompt属性失效
				if (opt.prompt && !this.onSuccess) {
					if (opt.prompt == 'messager') {
						$.messager.info(data.message);
					} else {
						MsgBox.info(data.message);
					}
				}
				// 执行成功回调监听
				opt.successMonitorsArr && $.each(opt.successMonitorsArr, function(index, item) {
					item && item.ajaxSuccess && item.ajaxSuccess(data, status, xhr);
				});
				try{
					opt.executeEmbedFunctions(function(item){
						item && item(data, status, xhr);
					}, 'onSuccess', this);
					this.onSuccess && this.onSuccess(data,status,xhr);
				}catch(e){
					//Logger.error("执行用户的success回调方法失败 e.message = " + e.stack);
					window['console'] && console.error(e.stack);
				}
			},
			'error':function(xhr,textStatus,errorThrown) {
				if (!xhr.hasDone) {
					MsgBox.error("访问服务器失败");
				}
				try{
					this.executeEmbedFunctions(function(item){
						item && item(xhr,textStatus,errorThrown);
					}, 'onError', this);
					this.onError && this.onError(xhr,textStatus,errorThrown);
				}catch(e){
					// Logger.error(e.message);
					window['console'] && console.error(e.stack);
				}
			},
			'beforeSend':function(xhr){
				if(!this.silent)
					MsgBox.startLoading();
				try{
					this.executeEmbedFunctions(function(item){
						item && item(xhr);
					}, 'onBeforeSend', this);
					this.onBeforeSend && this.onBeforeSend(xhr);
				}catch(e){
					// Logger.error(e.message);
					window['console'] && console.error(e.stack);
				}
			},
			'complete':function(xhr,textStatus){
				if(!this.silent)
					MsgBox.stopLoading();
				this.executeEmbedFunctions(function(item){
					item && item(xhr, textStatus);
				}, 'onComplete', this);
				this.onComplete && this.onComplete(xhr,textStatus);
			},
			'addParam':function(key,value) {
				if(this.data==undefined)
					this.data={};
				this.data[key] = value;
				return this;
			},
			'setData':function(data) {
				this.data = data;
				return this;
			},
			'tempUrl':function(func) {
				this.oUrl = this.url;
				var tUrl = func(this.url);
				this.url = tUrl;
				return this;
			}
		};
		ajaxSetting = $.extend(ajaxSetting, opt);
		window[ajaxSetting.id] = ajaxSetting;
		ajaxSetting.autoSend && ajaxSetting.send();
	},
	/*{id,ajax,onCurrentNodeSelected,onMutiNodesSelected,defaultSelectIndex,showRemoveBtn,
		canEdit,checkable,selectedMulti,showLine,dblClickExpand,
		convertToTemplate,nodeNameKey,nodeUrlKey,nodeCheckedKey,nodeChildrenKey,nodeTitleKey,
		nodeIdKey,parentIdKey,rootPidValue,maxLayer,className,dataStructure,silent,onAsyncError,
		onAsyncSuccess,onlyShowFolder,showIcon,drag,onDrag,rename,onDrop,style,selectRootNode, onFinishLoad
	}*/
	'tree':function(options) {
		ObjectUtil.cleanup(options, ['onAsyncError','onAsyncSuccess','onCurrentNodeSelected','onChecked','onMutiNodesSelected','convertToTemplate',
		    'ajax','onDrag','onDrop', 'onFinishLoad']);
		var opt = {
			'showRemoveBtn':false,
			'canEdit':false,
			'checkable':false,
			'showLine':true,
			'selectedMulti':false,
			'dblClickExpand':true,
			'defaultSelectIndex':0,
			'nodeNameKey':'text',
			'nodeUrlKey':'url',
			'nodeTitleKey':'title',
			'nodeChildrenKey':'children',
			'nodeCheckedKey':'checked',
			'nodeIdKey':'id',
			'parentIdKey':'pid',
			'rootPidValue':null,
			'maxLayer': 9999,
			'dataStructure':'array',
			'expandAll':false,
			'triggerRecorder':new TriggerRecorder(), // 影响树变化的触发点记录器
			'idStrategy':'uuid', // 生成ID的策略，可选值，uuid/timestamp/none，默认uuid
			'onlyShowFolder':false,  'showIcon':true,
			'drag':'none',           'isMove':false,
			'isCopy':false,          'rename':false,
			'style':'none',          'selectRootNode':false,
			'addDiyDom':null
		};
		
		opt = $.extend(opt, options);
		// 当可拖动时，canEdit设置为true
		if (opt.drag != 'none') {
			opt.canEdit = true;
			if (opt.drag == 'move') {
				opt.isCopy = !(opt.isMove = true);
			} else {
				opt.isCopy = !(opt.isMove = false);
			}
		}
		
		// 主题
		if (opt.style == 'outlook') {
			opt.addDiyDom = function(treeId, treeNode) {
				var spaceWidth = 5;
	            var switchObj = $("#" + treeNode.tId + "_switch"),
	            icoObj = $("#" + treeNode.tId + "_ico");
	            switchObj.remove();
	            icoObj.before(switchObj);

	            if (treeNode.level > 1) {
	                var spaceStr = "<span style='display: inline-block;width:" + (spaceWidth * treeNode.level)+ "px'></span>";
	                switchObj.before(spaceStr);
	            }
			};
		}
		
		if (opt.rename) {
			opt.canEdit = true;
		}
		opt.$tree = $('#' + opt.id);
		
		opt.stopLoading = function() {
			opt.$tree.closest('.m-loader-wrapper').stopLoading();
		};
		opt.startLoading = function() {
			opt.$tree.closest('.m-loader-wrapper').startLoading();
		};
		var oSucc = opt.ajax.onSuccess;
		opt.ajax.onSuccess = function(odata, status, xhr) {
			oSucc && oSucc(odata, status, xhr);
			opt.stopLoading();
	        // 数据处理
	        var data = null;
	        if (!(odata instanceof Array)) {
	            data = odata.info;
	        } else {
	            data = odata;
	        }
	        if (opt.dataStructure == 'array') {
	            data = $.toTree({
	                "data":data,
	                "rootPidValue":opt.rootPidValue,
	                "children":opt.nodeChildrenKey,
	                "contentDefine":{
	                    "id":opt.nodeIdKey,   "pid":opt.parentIdKey
	                }
	            });
	        }
            var setting = {
        		view : {
                    dblClickExpand: opt.dblClickExpand,           showLine: opt.showLine,    selectedMulti: opt.selectedMulti,
                    showIcon:opt.showIcon,                        addDiyDom:opt.addDiyDom
                },
                data:{
                    keep: {parent : true, leaf : false },
                    simpleData : {
                        enable : true,    idKey : opt.nodeIdKey,   pIdKey: opt.parentIdKey,    rootPId : ""
                    },
                    key:{
                        name: opt.nodeNameKey, 			url: opt.nodeUrlKey,    title: opt.nodeTitleKey,   checked: opt.nodeCheckedKey,
                        children: opt.nodeChildrenKey,  id:opt.nodeIdKey,       pid:opt.parentIdKey
                    }
                },
                edit: {
                    enable: opt.canEdit,  showRemoveBtn: opt.showRemoveBtn,   isCopy:opt.isCopy,  isMove:opt.isMove, showRenameBtn:opt.rename
                },
                callback : {
                    onClick : function(event, treeId, treeNode, clickFlag) { // 点击显示节点到内容
                        var zTree = $.fn.zTree.getZTreeObj(opt.id);
                        var nodes = zTree.getSelectedNodes();
                        opt.onMutiNodesSelected && opt.onMutiNodesSelected(nodes);
                        
                        // 限制仅单击时触发
                        $.excludeDbClick(opt.id, 250, function() {
                    		opt.onCurrentNodeSelected && opt.onCurrentNodeSelected(nodes[0]);
                        });
                        
                        return nodes;
                    },
                    onAsyncError: function(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {
                        opt.onAsyncError && opt.onAsyncError(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown);
                    },
                    onAsyncSuccess :function(event, treeId, treeNode, msg) {
                        opt.onAsyncSuccess && opt.onAsyncSuccess(event, treeId, treeNode, msg);
                    },
                    onCheck:function(event, treeId, treeNode) {
                    	opt.triggerRecorder.doChange();
                    	opt.onChecked && opt.onChecked(event, treeId, treeNode);
                    },
                    onDrag:function(event, treeId, treeNodes) {
                    	opt.onDrag && opt.onDrag(event, treeId, treeNodes);
                    },
                    beforeDrop:function(treeId, treeNodes, targetNode, moveType) {
                    	var nodeDepth = $.getTreeDepth(treeNodes[0], opt.nodeChildrenKey, opt.nodeIdKey);
                    	var targetNodeDepth = targetNode.level + 1;
                    	if (nodeDepth + targetNodeDepth > opt.maxLayer) {
                    		$.messager.info('移动失败，可以允许的最大层级为' + opt.maxLayer + ",移动后的最大层级为" + (nodeDepth + targetNodeDepth));
                    		return false;
                    	} 
                    	return true;
                    },
                    onDrop:function(event, treeId, treeNodes, targetNode, moveType) {
                    	opt.onDrop && opt.onDrop(event, treeId, treeNodes, targetNode, moveType);
                    }
                },
                check: {
                	chkStyle : "checkbox",
                	enable : opt.checkable, 
                	chkboxType : { "y" :"ps", "N" : "ps"}
                }
            };
            // data[opt.defaultSelectIndex].open = 'true';// 展开首页
            
            $.fn.zTree.init($("#"+opt.id), setting, data);
            if (opt.expandAll) {
            	$.fn.zTree.getZTreeObj(opt.id).expandAll(true);
            }
            
            if (opt.onlyShowFolder) {
            	// 控制叶子节点也显示为文件夹
            	$("#" + opt.id).addClass("ztree-only-folder");
        	}
            
            if (opt.style == 'outlook') {
            	var treeObj = $("#" + opt.id);
            	treeObj.addClass("showIcon");
//            	treeObj.hover(function () {
//            		if (!treeObj.hasClass("showIcon")) {
//            			treeObj.addClass("showIcon");
//            		}
//            	}, function() {
//            		treeObj.removeClass("showIcon");
//            	});
            }
            
            var tree = window[opt.id];
            if (opt.selectRootNode) {
            	tree.selectFirstRootNode();
            }
            opt.onFinishLoad && opt.onFinishLoad();
		};
		var onError = opt.ajax.onError;
		opt.ajax.onError = function(xhr,textStatus,errorThrown) {
			opt.stopLoading();
			onError && onError(xhr,textStatus,errorThrown);
		};
		var onComplete = opt.ajax.onComplete;
		opt.ajax.onComplete = function(xhr,textStatus) {
			opt.stopLoading();
			onComplete && onComplete(xhr,textStatus);
		};
		var onBeforeSend = opt.ajax.onBeforeSend;
		opt.ajax.onBeforeSend = function(xhr) {
			opt.silent || opt.startLoading();
			onBeforeSend && onBeforeSend(xhr);
		};
		var tree = {
			'recorder':new Recorder(),
			// 获取操作记录器
			'getRecorder':function() {
				return this.recorder;
			},
			'getRootNode':function() {
				var treeObj = this.getZTreeObj();
				var nodes = treeObj.getNodes();
				return nodes;
			},
			// 隐藏节点及其子节点
			'hideNodes':function(nodes) {
				if (nodes == null || nodes.length <= 0) {
					return ;
				}
				var tree = this.getZTreeObj();
				tree.hideNodes(nodes);
				var that = this;
				$.each(nodes, function(index, item) {
					var children = item[opt.nodeChildrenKey];
					that.hideNodes(children);
				});
			},
			// 显示节点及其子节点
			'showNodes':function(nodes) {
				if (nodes == null || nodes.length <= 0) {
					return ;
				}
				var tree = this.getZTreeObj();
				tree.showNodes(nodes);
				var that = this;
				$.each(nodes, function(index, item) {
					var children = item[opt.nodeChildrenKey];
					that.showNodes(children);
				});
			},
			// 根据关键词搜索
			'search':function(key) {
				var rootNodes = this.getRootNode();
				if ($.trim(key)) {
					var tree = this.getZTreeObj();
					var showAndExpanParentNode = function(node, tree) {
						if (node.isHidden) {
							tree.showNode(node);
						}
						if (!node.open) {
							tree.expandNode(node);
						}
						if (node.getParentNode()!=null) {
							showAndExpanParentNode(node.getParentNode(), tree);
						}
					};
					// 1.隐藏全部
					this.hideNodes(rootNodes);
					//2.查找节点
					var node = tree.getNodesByParamFuzzy(opt.nodeNameKey, key);
					$.each(node, function(index, item){
						showAndExpanParentNode(item, tree);
					});
					this.showNodes(node);
				} else {
					this.showNodes(rootNodes);
					this.doExpandAll(false);
				}
			},
			// 选中第一个节点
			'selectFirstRootNode': function(){
				var treeObj = this.getZTreeObj();
				var nodes = treeObj.getNodes();
				if (nodes.length > 0) {
					treeObj.selectNode(nodes[0]);
					opt.onCurrentNodeSelected && opt.onCurrentNodeSelected(nodes[0]);
				}
			},
			// 选中节点，node:节点对象，zTree 内部的数据对象
			// 			zTree 内部的数据对象，true:表示追加选中，会出现多点同时被选中的情况
			//   		                                      ，false表示单独选中，原先被选中的节点会被取消选中状态
			'selectNode': function(node,addFlag) {
				var treeObj = this.getZTreeObj();
				treeObj.selectNode(node,addFlag);
				// 触发选中事件
				this.onCurrentNodeSelected && this.onCurrentNodeSelected(node);
			},
			// 将ztree节点转为你所需要的节点
			'converNodeToTemplate':function(node,index){
				return node;
			},
			// 将ZTree 的nodes实例转为你所需要的nodes
			'getZTreeNodesToTemplates': function(){
				var treeObj = $.fn.zTree.getZTreeObj(this.id);
				var nodes = treeObj.transformToArray(treeObj.getNodes());
				var arr = new Array();
				
				var _this = this;
				$.each(nodes,function(index,item){
					var nodeIndex = treeObj.getNodeIndex(item); // 当前节点在同级节点中的第几个节点
					var template = _this.converNodeToTemplate(item,nodeIndex);
					arr.push(template);
				});
				return arr;
			},
			// 更新一个节点, 
			'updateNode': function(node,refresh){
				var zTree = this.getZTreeObj();
				refresh = refresh ==undefined ? true: refresh;
				zTree.updateNode(node, refresh);// 执行内容更改
				this.recorder.getUpdateRecords().put(node);
			},
			// 
			'getJsonArrayOfNodes': function(){
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				var nodes = treeObj.transformToArray(treeObj.getNodes());
				var jsonArr = JSON.stringify(nodes);
				return jsonArr;
			},
			// 获取ZTree对象
			'getZTreeObj': function(){
				return $.fn.zTree.getZTreeObj(opt.id);
			},
			// 展开所有节点
			'expandAll': function(){
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				treeObj.expandAll(true);
			},
			// 设置选中或取消所有节点，false:取消所有勾选/true:勾选所有 默认
			'checkAllNodes': function(flag){
				flag = (flag == "false" || flag == false)?false:true;
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				treeObj.checkAllNodes(flag);
			},
			// 根据id数组来选中节点
			'checkNodesWithIdArray': function(nodeIdArr,checked, beforeCancelAll, checkTypeFlag,callbackFlag){
				checked == (checked=="false"||checked==false) ? false : true;
				checkTypeFlag == (checkTypeFlag=="true" || checkTypeFlag==true) ? true : false;
				callbackFlag == (callbackFlag=="true" || callbackFlag==true) ? true : false;
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				beforeCancelAll == false || treeObj.checkAllNodes(false);
				if(nodeIdArr != undefined && nodeIdArr != null){
					for(var i=0;i<nodeIdArr.length;i++){
						var node = treeObj.getNodeByParam(opt.nodeIdKey, nodeIdArr[i], null);
						treeObj.checkNode(node,checked,checkTypeFlag,callbackFlag);
					}
				}
			},
			// 获取选中的节点
			'getCheckNodes': function(flag){
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				flag == (flag=="false"||flag==false)?false:true;
				return treeObj.getCheckedNodes(flag);
			},
			// 获取所有选中节点的id
			'getCheckedNodeIds':function(flag) {
				var nodes = this.getCheckNodes(flag);
				return $.toPropertyValueArray(nodes, opt.nodeIdKey);
			},
			// 获取所有选中的叶子节点
			'getCheckedLeafNodes': function(flag) {
				var nodes = this.getCheckNodes(flag);
				if (nodes == null && nodes.length <= 0) {
					return [];
				}
				var mnodes = new GenericSet(nodes);
				return mnodes.getItemsByKey('isParent', false);
			},
			// 获取所有选中的叶子节点的id
			'getCheckedLeafNodesIds': function(flag) {
				var nodes = this.getCheckedLeafNodes(flag);
				return $.toPropertyValueArray(nodes, opt.nodeIdKey);
			},
			// 根据id 查找节点
			'_findNodeById': function(nodes,idKey,childrenKey,id) {
			    for(var i=0; i < nodes.length; i++){
			        var item = nodes[i];
			        var tItem = this._findNodeById(item[childrenKey],idKey,childrenKey,id);
			        if (tItem != null) {
			            return tItem;
			        }
			        if (item[idKey] == id) {
			            return item;
			        }
			    }
			    return null;
			},
			'selectNodeById': function(id) {
				this.selectNode(this.findNodeById(id));
			},
			'findNodeById': function(id) {
				/*this.keys.nodeId*/
				var treeObj = this.getZTreeObj();
				var nodes = treeObj.getNodes();
				return this._findNodeById(nodes, this.keys.id, this.keys.children, id);
			},
			'getNodes': function(){
				var treeObj = this.getZTreeObj();
				var nodes = treeObj.getNodes();
				return nodes;
			},
			'getSelectedNodes': function(){
				var treeObj = $.fn.zTree.getZTreeObj(opt.id);
				var nodes = treeObj.getSelectedNodes();
				return nodes;
			},
			'getCurrentNode': function() {
				var nodes = this.getSelectedNodes();
				return nodes[0];
			},
			'cancelSelectedNode': function(node){
				node && this.getZTreeObj().cancelSelectedNode(node);
			},
			'cancelAllSelectedNodes': function(){
				this.getZTreeObj().cancelSelectedNode();
			},
			'removeNode': function(node) {
				if(node && node.id) {
					this.recorder.getDeleteRecords().put(node);
					this.getZTreeObj().removeNode(node);
					return true;
				}
				return false;
			},
			'addNode': function(node){
				// 组装节点信息
				var childNode = {};
				childNode['id'] = childNode[opt.nodeIdKey] = $.generateId(this.idStrategy);
				childNode[opt.nodeNameKey] = '新节点';
				
				// 向ztree中增加了新的节点后，返回当前节点及其子节点
				var newNodes = null; 
				var treeObj = this.getZTreeObj();
				if(node==null) { // 传入null，那么新增根节点
					newNodes = treeObj.addNodes(null, childNode);
				}else{
					var parentId = node[opt.nodeIdKey];
					if(!parentId) { // 选中节点没有id
						Logger.error("你所选中的节点id值为 null");
						return {};
					}
					childNode[opt.parentIdKey] = parentId;
					var parentZNode = node;
					if (parentZNode.level >= (opt.maxLayer-1) && opt.maxLayer != -1) {
						$.messager.info('添加新节点失败，你最多可以添加到第' + opt.maxLayer + '级');
						return {};
					}
					newNodes = treeObj.addNodes(parentZNode, childNode, true); // 得到新增加的节点
				}
				// 选中新增加的节点
				treeObj.selectNode(newNodes[0]); 
				this.recorder.getNewRecords().put(newNodes[0]);
				Logger.info("你正在新增ztree节点，新增的节点："+JSON.stringify(newNodes));
				return newNodes[0];
			},
			'refresh': function(flag){
				if (flag) {
					this.getRecorder().clearAll();
					opt.ajax.send();
				} else {
					this.getZTreeObj().refresh();
				}
			},
			// 展开/折叠所有节点
			'doExpandAll':function(flag) {
				this.getZTreeObj().expandAll(flag);
			},
			'getTriggerRecorder':function() {
				return this.triggerRecorder;
			}
		};
		
		tree = $.extend(tree, opt);
		window[opt.id] = tree;
		tree.ajax.send();
	},
	'operBar':function(options) {
		ObjectUtil.cleanup(options, ["onAdd","onDelete","onRefresh","onSave",'onSub']);
		var opt = {
			'style':'icon',
			'relations':{
				'icon':'ICON_SETTINGS'
			},
			'ICON_SETTINGS':{
				'items':{
					'delete':      { 'icon':'fa fa-trash fa-fw',   'text':'删除', 'funcName':'onDelete' },
					'sub':         { 'icon':'fa fa-minus fa-fw',   'text':'删除', 'funcName':'onSub'  },
					'add':         { 'icon':'fa fa-plus fa-fw' ,   'text':'添加', 'funcName':'onAdd'  },
					'refresh':     { 'icon':'fa fa-refresh fa-fw', 'text':'刷新', 'funcName':'onRefresh'  },
					'save':        { 'icon':'fa fa-save fa-fw',    'text':'保存', 'funcName':'onSave'  },
				},
				'getItemNode':function(mOpt, item) {
					var mItem = this.items[item];
					var $p = $("<a href='javascript:void(0);'><i></i></a>");
					$p.attr('title',mItem.text);
					$p.find('i').addClass(mItem['icon']);
					$p.off('click').on('click', function(e) {
						e.stopPropagation();
						e.preventDefault();
						mOpt[mItem.funcName] && mOpt[mItem.funcName](e); 
					});
					return $p;
				}
			}
		};
		$.extend(opt, options);
		var settings = opt[opt.relations[opt.style]];
		var items = opt.items.split(",");
		var $operBar = $("*[data-oper-bar='" + opt.id + "']");
		$operBar.attr('data-' + opt.style, "true");
		for (var i in items) {
			var item = items[i];
			var $node = settings.getItemNode(opt, item);
			$operBar.append($node);
		}
	},
	'datatable':function(options) {
		ObjectUtil.cleanup(options, ["ajax","afterReady","afterSort","onChecksChanged",
		                         "onRenderItem","onDoubleClick","onItemClick", "dataset"]);
		var opt = {
			'showLineNumber':true,
		};
		$.extend(opt, options);
		window[opt.id] = $("[data-datatable='" + opt.datatableId + "']#" + opt.id).datatable(opt);
	},
	'pagination':function(options) {
		ObjectUtil.cleanup(options, ["datatable"]);
		var opt = {
			'showPageChoice':true
		};
		$.extend(opt, options);
		var $pagination = $("#" + opt.id + "[data-pagination='" + opt.paginationId + "']");
		var mPagination = window[opt.id] = $pagination.pagination({
			'id': opt.id,
			'ajax': opt.datatable.getAjax(),
			'$pagination':$pagination,
			'rows':opt.pageSize,
			'datatable':opt.datatable,
			'pageChoice':opt.pageChoice,
			'showPageChoice':opt.showPageChoice,
			'pageSize':opt.pageSize
		});
		opt.datatable.setPagination(mPagination);
		mPagination.refresh();
	},
	/**
	 * 
	 * @参数 {dropValues}
	 */
	'dropValues':function(options) {
		// onSuccess, onChange
		ObjectUtil.cleanup(options, ["onValueChanged", "dropValues", "handleRowData"]);
		// 构造和替换select
		var buildSelect = function(opt) {
			if (opt.dropValues && !ArrayUtil.isArray(opt.dropValues)) {
				var arr = [];
				$.each(opt.dropValues, function(key, value) {
					var item = {};
					item[opt.contentDefine.text] = value;
					item[opt.contentDefine.value] = key;
					arr.push(item);
				});
				opt.dropValues = arr;
			}
			opt.data = opt.dropValues;
			if (opt.ext1AsDefault && opt.defaultValue == null) {
				var arr = $.toPropertyValueArray(opt.dropValues, 'ext1');
				$.each(arr, function(index, item) {
					if (item != null) {
						opt.defaultValue = item;
					}
				});
			}
			
			var $select = $._buildSelect(opt);
			$select.attr("data-tag", "dropList");
			$("#" + opt.id + "[data-tag='dropList']").replaceWith($select);
		};
		
		var opt = {
			'showSelectName':'请选择',
			'showSelectAll':false,
			'async':false,
			'contentDefine':{
				'text':(function() {
					if (StringUtil.isNotBlank(options.textDefine)) {
						return options.textDefine;
					}
					return 'codeInfoName';
				})(),
				'value':(function() {
					if (StringUtil.isNotBlank(options.valueDefine)) {
						return options.valueDefine;
					}
					return 'codeInfoValue';
				})()
			},
			'setData': function(data) {
				this.dropValues = data;
				buildSelect(this);
			}
		};
		$.extend(opt, options);
		
		window[opt.id] = opt;
		
		buildSelect(opt);
	},
	// 日期时间选择控件
	// options = {name, id, dateFormat, dateType, readonly, defaultNow, value, startDate, endDate, clearBtn}
	datepicker:function(options) {
		ObjectUtil.cleanup(options, []);
		var opt = {
			'readonly':true, 'clearBtn': true
		};
		$.extend(opt, options);
		var $this = $("div[data-link-field='" + opt.id + "']");
		
		var DATAPICKER_SETTING = {
			'date':{
				'buildBtn':function() {
					if (opt.clearBtn) {
						$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-remove'></i></span>");
					}
					$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-calendar'></i></span>");
				},
				'setting':{
					'language':'zh-CN',
					'format':(function(){
						if (StringUtil.isBlank(opt.dateFormat)) {
							return 'yyyy-mm-dd';
						}
						return opt.dateFormat;
					})(),
					'weekStart': 1,
			        'todayBtn':  1,
					'autoclose': 1,
					'todayHighlight': 1,
					'startView': 2,
					'forceParse': 0,
			        'showMeridian': 1,
			        'minView': 2,
			        'startDate':(function(){
			        	if (opt.startDate) {
			        		return DateUtil.strToDate(opt.startDate);
			        	}
			        	return null;
			        })(),
			        'endDate':(function(){
			        	if (opt.endDate) {
			        		return DateUtil.strToDate(opt.endDate);
			        	}
			        	return null;
			        })(),
				},
			},
			'datetime':{
				'buildBtn':function() {
					if (opt.clearBtn) {
						$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-remove'></i></span>");
					}
					$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-th'></i></span>");
				},
				'setting':{
					'language':'zh-CN',
					'format':(function(){
						if (StringUtil.isBlank(opt.dateFormat)) {
							return 'yyyy-mm-dd hh:ii:ss';
						}
						return opt.dateFormat;
					})(),
					'weekStart': 1,
			        'todayBtn':  1,
					'autoclose': 1,
					'todayHighlight': 1,
					'startView': 2,
					'forceParse': 0,
			        'showMeridian': 1,
				}
			},
			'time':{
				'buildBtn':function() {
					if (opt.clearBtn) {
						$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-remove'></i></span>");
					}
					$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-time'></i></span>");
				},
				'setting':{
					'language':'zh-CN',
					'format':(function(){
						if (StringUtil.isBlank(opt.dateFormat)) {
							return 'hh:ii:ss';
						}
						return opt.dateFormat;
					})(),
					'weekStart': 1,
			        'todayBtn':  1,
					'autoclose': 1,
					'todayHighlight': 1,
					'startView': 1,
					'minView': 0,
					'maxView': 1,
					'forceParse': 0,
				}
			},
			'month': {
				'buildBtn':function() {
					if (opt.clearBtn) {
						$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-remove'></i></span>");
					}
					$this.append("<span class='input-group-addon add-on'><i class='glyphicon glyphicon-th'></i></span>");
				},
				'setting':{
					'language':'zh-CN',
					'format':(function(){
						if (StringUtil.isBlank(opt.dateFormat)) {
							return 'yyyy-mm';
						}
						return opt.dateFormat;
					})(),
					'weekStart': 1,
			        'todayBtn':  1,
					'autoclose': 1,
					'todayHighlight': 1,
					'startView': 3,
					'minView': 3,
					'maxView': 1,
					'forceParse': 0,
					'startDate':(function(){
			        	if (opt.startDate) {
			        		return DateUtil.strToDate(opt.startDate);
			        	}
			        	return null;
			        })(),
			        'endDate':(function(){
			        	if (opt.endDate) {
			        		return DateUtil.strToDate(opt.endDate);
			        	}
			        	return null;
			        })(),
				}
			}
		};
		var buildDatetimepicker = function(opt) {
			// 清理恢复
			$this.datetimepicker('remove'); // 移除日期时间选择器。同时移除已经绑定的event、内部绑定的对象和HTML元素。
			$this.empty(); // 先清空内部内容
			
			// 构建
			var $input = $('<input class="form-control m-o-input" size="16" type="text" value="" data-input="true">');
			$this.append($input); // 在把内部的输入框拼接上去
			
			if (opt.readonly) {
				$this.find("input[data-input='true']").attr('readonly', 'readonly');
			}
			// 设置opt.dateFormat属性
			opt.dateFormat = DATAPICKER_SETTING[opt.dateType].setting.format;
			// 设置data-date-format属性
			$this.attr("data-date-format", opt.dateFormat);
			$this.attr("data-link-format", opt.dateFormat);
			
			DATAPICKER_SETTING[opt.dateType].buildBtn();
			if (StringUtil.isNotBlank(opt.value)) {
				$this.attr({
					"data-date": opt.value,
					"value": opt.value
				});
			}
			$this.datetimepicker(DATAPICKER_SETTING[opt.dateType].setting);
			if (opt.defaultNow) {
				$this.datetimepicker('setValue');
			}
		};
		opt.setDateType = function(dateType) {
			opt.dateType = dateType;
			buildDatetimepicker(this);
		};
		buildDatetimepicker(opt);
		window[opt.id] = opt;
	},
	// markdown 编辑器
	// options = {id, width, height}
	'mdeditor':function(options) {
		ObjectUtil.cleanup(options, []);
		var opt = {
			'saveHTMLToTextarea':true,
			'path':ctx + '/res/libs/editor.md/',
			'pluginPath':ctx + '/res/libs/editor.md/plugins/',
			'emoji':false
		};
		$.extend(opt, options);
		
		window[opt.id] = editormd(opt.id, {
			'width':opt.width, 
			'height':opt.height,
			'saveHTMLToTextarea' : true,
			'path':opt.path,
			'pluginPath':opt.pluginPath,
			'emoji':opt.emoji,
			'taskList' : true,
            'tocm': true,         // Using [TOCM]
            'tex' : true,                   // 开启科学公式TeX语言支持，默认关闭
            'flowChart' : true,             // 开启流程图支持，默认关闭
            'sequenceDiagram' : true,       // 开启时序/序列图支持，默认关闭,
			'editorTheme': "mdn-like",
            'theme': "gray",
            'previewTheme': "mdn-like",
            'imageUpload':true,
            'imageFormats'   : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            'imageUploadURL' : ctx + '/datum/file/markdown/doUpload',
            'toolbarIcons' : function() {
                return ["undo", "redo", "|", "bold", 'italic', 'quote', 'del', "hr", "|", "h1", "h2", "h3", "h4",
                        "|", "list-ul", "list-ol",  "|", 'emoji', 'link', 'datetime', 'code', "code-block", 'table', 'image',
                        "||", "watch", "fullscreen", "preview"];
            },
		});
	},
	// 富文本编辑器
	// {id, basePaht, bodyClass, className, allowFileManager, height, width, allowImageRemote, name, actionBarMode}
	kindeditor:function(options) {
		ObjectUtil.cleanup(options, ['fillAjax']);
		var opt = {
			'bodyClass':'article-content',        'name':null,                 'height':"300px",            'width':"100%",
			'allowFileManager':true,              'allowImageRemote':false,    'actionBarMode': 'simple', 
			'syncContent': true
	    };
		$.extend(opt, options);
		
		var kindeditorItems = $.store.get("KINDEDITOR_ITEMS");
		if (kindeditorItems == null) {
			kindeditorItems = {
				'simple': ['fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
				           'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
				           'insertunorderedlist', '|', 'emoticons', 'image', 'link'],
				'full': [
	                       'undo', 'redo', '|',
	                       'preview', 'code', 'cut', 'copy', 'paste','plainpaste', 'wordpaste', '|',
	                       'justifyleft', 'justifycenter', 'justifyright',
	                       'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
	                       'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 
	                       'fullscreen', '/',
	                       'formatblock', 'fontname', 'fontsize', '|', 
	                       'forecolor', 'hilitecolor', 'bold',
	                       'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 
	                       'image', 'table', 'hr', 'pagebreak','anchor', 'link', 'unlink']
			};
			$.store.set("KINDEDITOR_ITEMS", kindeditorItems);
		}
		window[opt.id] = KindEditor.create("#" + opt.id + "[data-tag='kindeditor']", {
			'basePath': opt.basePath,
			'bodyClass' : opt.bodyClass,
			'items' : kindeditorItems[opt.actionBarMode],
	        'allowFileManager' : opt.allowFileManager,
	        'height':opt.height,
	        'width': opt.width,
	        'allowImageRemote': opt.allowImageRemote,
	        'afterBlur': function() {
	        	if (opt.syncContent) {
	        		this.sync();
	        	}
	        },
	        'ajaxSuccess': function(data, statux, xhr) {
	        	this.html(data.info[opt.name]);
	        }
		});
	},
	'boards': function(options) {
		ObjectUtil.cleanup(options, []);
		var opt = {
			
		};
		$.extend(opt, options);
		var $boards = $("#" + opt.id + "[data-tag='boards']");
		if ($boards.hasClass("m-fixed")) {
			var boardsHeight = $.getTopBody().find(".article-box").height()
					- ($.getTopBody().find(".article-box .f-tabset").height() 
						+ parseInt($.getTopBody().find(".article-box .f-tabset").css("padding-bottom")) 
						+ parseInt($.getTopBody().find(".article-box .f-tabset").css("padding-top"))
						+ parseInt($.getTopBody().find(".article-box .f-tabset").css("margin-top")) 
						+ parseInt($.getTopBody().find(".article-box .f-tabset").css("margin-bottom")));
			$boards.css({
				'height': boardsHeight + 'px',
				'overflow': 'hidden'
			});
			$boards.children(".m-board").each(function(index, item) {
				var boardHeight = boardsHeight - $(this).children(".panel-heading").height();
				$(this).children('.panel-body').css({
					"height": boardHeight + 'px',
					'overflow': 'auto',
					'box-sizing': 'content-box'
				});
			});
		}
	},
	// id, ajaxAvailable, ajaxSelected, valueDefine, name, textDefine, showHeader
	'mutiSelect':function(options) {
		ObjectUtil.cleanup(options, ['ajaxSelected', 'ajaxAvailable']);
		var opt = {
			'odata': { // 缓存原始数据
				'available': null,
				'selected': null
			},
			'data':{
				'available': null, // type is GenericSet
				'selected': null, // type is GenericSet
				'merge': function() {
					if (ArrayUtil.hasData(this.available.arr)) {
						return this.available.rejectByKey(this.selected, 'id');
					}
					return this.available;
				},
				// 获取左边选中的部分
				'getLeftSelected': function() {
					return this.available.getItemsByKey('selected', true);
				},
				// 获取右边选中的部分
				'getRightSelected': function() {
					return this.selected.getItemsByKey('selected', true);
				}
			},
			'showHeader': false, 'mutiple': false,
			'textDefine': null, 'valueDefine': null,
			'clickStart': null
		};
		$.extend(opt, options);
		
		// ajaxSelected和ajaxAvailable一定是同步的ajax
		opt.ajaxSelected.async = false;
		opt.ajaxAvailable.async = false;
		
		opt.$mutiSelect = $("#mutiSelect_" + opt.id + "[data-tag='mutiSelect']");
		opt.$header = opt.$mutiSelect.find("[data-element='header']");
		opt.$body = opt.$mutiSelect.find("[data-element='body']");
		opt.$footer = opt.$mutiSelect.find("[data-element='footer'] td");
		opt.$available = opt.$mutiSelect.find("[data-element='available']");
		opt.$selected = opt.$mutiSelect.find("[data-element='selected']");
		opt.$handle = opt.$mutiSelect.find("[data-element='handle']");
		
		// 是否显示头部
		if (opt.showHeader) {
			opt.$header.removeAttr("hidden");
		}
		
		// 计算$available和$selected的宽度
		var calculateWidthAndSet = function() {
			var HANDLE_BAR_WIDTH = 35; // 操作栏的宽度
			var width = opt.$mutiSelect.width();
			var listContainerWidth = ((width - HANDLE_BAR_WIDTH) / 2) + 'px';
			opt.$selected.css('width', listContainerWidth);
			opt.$available.css('width', listContainerWidth);
			opt.$available.find(".m-list").css('width', listContainerWidth);
			opt.$selected.find(".m-list").css('width', listContainerWidth);
		};
		calculateWidthAndSet();
		
		var switchFocusState = function(ele, selStatus) {
			opt.$body.find("a[data-focus]").removeAttr("data-focus");
			!selStatus ? $(ele).removeAttr('data-focus') : $(ele).attr('data-focus', 'focus');
		};
		
		// 视图重新构造
		var rebuild = function(id) {
			buildListView('selected', opt.data.selected);
			buildListView('available', opt.data.merge());
			
			opt.$body.find("a[data-value='" + id + "']").closest("ul").find("a[selected]").removeAttr("selected");
			if (ArrayUtil.isArray(id)) {
				var arr = id;
				$.each(arr, function(index, item) {
					opt.$body.find("a[data-value='" + item + "']").attr({
						"selected": "selected",
						"data-focus": "focus"
					});
				});
			} else {
				opt.$body.find("a[data-value='" + id + "']").attr({
					"selected": "selected",
					"data-focus": "focus"
				});
			}
			setValue();
		};
		
		// 左移动到右边，右移动到左边的事件处理函数
		var singleElementClickEvent = function(type, $ele) {
			var values = new Array();
			$ele.each(function(index, item) {
				var id = $(this).data("value");
				var moveItem = opt.data[type].getItemByKey('id', id);
				if (!moveItem) {
					return ;
				}
				opt.data[type].removeByKey(moveItem, 'id');
				// 相反类型
				var inverseType = (type == 'selected' ? 'available': 'selected');
				opt.data[inverseType].putByKey(moveItem, 'id');
				
				values.push(id);
			});
			if (values.length == 1) {
				values = values[0];
			}
			rebuild(values);
		};
		
		// 构造列表
		var buildListView = function(type, data) {
			var $container = (type == 'available' ? opt.$available : opt.$selected);
			var genericSet = data;
			
			var $ul = $("<ul class='m-list'></ul>");
			$container.find("ul").remove(); // 先移除
			$container.append($ul);
			$.each(genericSet.arr, function(index, nItem) {
				var item = nItem.data;
				
				var $li = $("<li></li>");
				var $a = $("<a href='javascript:void(0);'></a>");
				var value = item[opt.valueDefine];
				var text = item[opt.textDefine];
				$a.attr({
					'data-value':value,
					'data-text':text,
					'data-tag':'element',
					'data-index': index
				});
				// 单击事件
				$a.on('click', function(e) {
					e.stopPropagation();
					e.preventDefault();
					
					var $part = opt['$' + type].find("a[data-tag='element']");
					if(e.shiftKey) {
						var si = $(opt.clickStart).data("index");
						var ti = $(this).data("index");
						var $sel = $part.slice(Math.min(si, ti), Math.max(si, ti) + 1);		
						$sel.attr({
							"selected": "selected",
							'data-focus': 'focus'
						});
						$part.not($sel).removeAttr("selected");
						$part.not($sel).removeAttr("data-focus");
						return;
					} else if (e.ctrlKey) {
						if($(this).attr("selected")){
							$(this).removeAttr("selected");
							$(this).removeAttr("data-focus");
						} else {
							$(this).attr({
								"selected": "selected",
								'data-focus': 'focus'
							});
						}
						return;
					}
					opt.clickStart = this;
					$(this).attr({
						"selected": "selected",
						'data-focus': 'focus'
					});
					$part.not($(this)).removeAttr("selected");
					$part.not($(this)).removeAttr("data-focus");
					
					var linkVal = $(this).data('value');
					var linkItem = opt.data[type].getItemByKey('id', linkVal);
					$container.find('a[selected]').removeAttr('selected');
					var selStatus = $(this).attr("selected") == null ? true : false;
					linkItem['selected'] = selStatus;
					!selStatus ? $(this).removeAttr('selected') : $a.attr('selected', 'selected');
					
					switchFocusState(this, selStatus);
					
				});
				// 双击事件
				$a.on('dblclick', function(e) {
					e.stopPropagation();
					e.preventDefault();
					singleElementClickEvent(type, $(this));
				});
				$a.text(text);
				$li.append($a);
				$ul.append($li);
			});
			calculateWidthAndSet();
		};
		
		// 操作栏的事件处理
		var handleEvent = function() {
			var $allToRight = opt.$handle.find("[data-handle='all-to-right']");
			var $allToLeft = opt.$handle.find("[data-handle='all-to-left']");
			var $oneToRight = opt.$handle.find("[data-handle='one-to-right']");
			var $oneToLeft = opt.$handle.find("[data-handle='one-to-left']");
			
			$oneToRight.on('click', function(e) {
				// 所有左侧选中的，移动到右侧去
				singleElementClickEvent('available', opt.$available.find("a[selected='selected']"));
			});
			$allToRight.on('click', function(e) {
				// 所有左侧的，移动到右侧去
				opt.data.selected.merge(opt.data.available);
				var availableIds = $.toPropertyValueArray(opt.data.available.arr, 'id');
				opt.data.available.clear();
				rebuild(availableIds);
			});
			$allToLeft.on('click', function(e) {
				// 所有左侧的，移动到右侧去
				opt.data.available.merge(opt.data.selected);
				var selectedIds = $.toPropertyValueArray(opt.data.selected.arr, 'id');
				opt.data.selected.clear();
				rebuild(selectedIds);
			});
			$oneToLeft.on('click', function(e) {
				// 所有右侧选中的，移动到左侧去
				singleElementClickEvent('selected', opt.$selected.find("a[selected='selected']"));
			});
		};
		
		// 加工数据
		var processData = function(arr, type) {
			if (!ArrayUtil.isArray(arr)) {
				return ;
			}
			var newArr = [];
			// opt.data.selected   opt.data.available
			$.each(arr, function(index, item) {
				var newObj = {
					'visiable': false,
					'id': item[opt.valueDefine],
					'data': item
				};
				newArr.push(newObj);
			});
			opt.data[type] = new GenericSet(newArr);
		};
		
		// 给表单设值
		var setValue = function() {
			var values = new Array();
			opt.$selected.find("a[data-tag='element']").each(function(index, item) {
				var value = $(this).data("value");
				values.push(value);
			});
			opt.$select.val(values);
		};
		
		// 获取数据
		// 可选部分
		opt.ajaxAvailable.embedFunction("onSuccess", function(data,status,xhr) {
			// 兼容
			if (ArrayUtil.isArray(data.info)) {
				opt.odata.available = data.info; // 将已选数据存入opt.data
			} else {
				opt.odata.available = data.info[opt.name];
			}
		}, opt.ajaxAvailable);
		!opt.ajaxAvailable.autoSend && opt.ajaxAvailable.send();
		
		// 已选部分
		if (opt.ajaxSelected) {
			opt.ajaxSelected.embedFunction("onSuccess", function(data,status,xhr) {
				// 兼容
				if (ArrayUtil.isArray(data.info)) {
					opt.odata.selected = data.info; // 将已选数据存入opt.data
				} else {
					if (data.info == null) {
						opt.odata.selected = [];
					} else {
						opt.odata.selected = data.info[opt.name];
					}
				}
				processData(opt.odata.selected, 'selected'); // 加工数据
				buildListView('selected', opt.data.selected);
				
				// 剔除
				processData(opt.odata.available, 'available'); // 加工数据
				buildListView('available', opt.data.merge());
				
				// 表单对象
				var $select = $._buildSelect({
					'id': opt.id, 'name': opt.name, 
					'contentDefine': { 'text': opt.textDefine, 'value': opt.valueDefine },
					'data': opt.odata.available
				});
				$select.attr({
					"hidden": "hidden",
					"multiple": "multiple"
				});
				opt.$footer.find("select").remove();
				opt.$footer.append($select);
				opt.$select = $select;
				// 设值
				setValue();
				
				handleEvent(); // 操作栏的事件处理
			}, opt.ajaxSelected);
		}
		!opt.ajaxSelected.autoSend && opt.ajaxSelected.send();
		
		// 扩展一些方法 
		var mutiSelect = {
			'getSelectedAvailableItems': function(state) {
				if (state == undefined) {
					state = true;
				}
				var arr = opt.data.available.getItemsByKey('selected', state);
				return $.toPropertyValueArray(arr, 'data');
			},
			'val': function() {
				return opt.$select.val();
			}
		};
		$.extend(opt, mutiSelect);
		window[opt.id] = opt;
	},
};





